package com.xhs.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * @desc: CompletableFuture 多任务组合回调
 * @projectName: java-tools-parent
 * @author: xhs
 * @date: 2025-08-09 周六 16:10
 */
@Slf4j
@RestController
@RequestMapping("/completableFuture2")
public class CompletableFuture2Controller {

    @Resource
    private Executor taskExecutor;

    /**
     * allOf 等待所有任务都执行完，再向下执行任务。
     * 因为每个任务的执行结果类型可能不同，所以allOf返回为Void,需要单独获取每个future的结果
     */
    @GetMapping("/test01")
    public void test01() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程："+Thread.currentThread().getName());
            try {
                Thread.sleep(5000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "线程A";
        },taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程："+Thread.currentThread().getName());
            return "线程B";
        },taskExecutor);

        CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> {
            log.info("任务C线程："+Thread.currentThread().getName());
            return "线程C";
        },taskExecutor);

        CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futureA,futureB,futureC);
        log.info("allOfFuture.join():{}",allOfFuture.join());
        log.info("最终结果："+futureA.get()+futureB.get()+futureC.get());

        List<CompletableFuture<String>> futureList = new ArrayList<>();
        futureList.add(futureA);
        futureList.add(futureB);
        futureList.add(futureC);
        CompletableFuture<List<String>> resultFuture = CompletableFuture
                .allOf(futureList.toArray(new CompletableFuture[3]))
                .thenApply(v-> futureList.stream().map(CompletableFuture::join).collect(Collectors.toList()));
        log.info("resultFuture.get():{}",resultFuture.get());
    }

    /**
     * anyOf 其中任何一个任务执行完，都向下执行任务,返回最早执行完的任务的执行结果
     */
    @GetMapping("/test02")
    public void test02() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程："+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        },taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程："+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "world";
        },taskExecutor);

        CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> {
            log.info("任务C线程："+Thread.currentThread().getName());
            return "线程C";
        },taskExecutor);

        // 获取最早执行完任务的结果
        CompletableFuture<Object> finalResult = CompletableFuture.anyOf(futureA,futureB,futureC);
        log.info("最终结果："+finalResult.get());

    }
}
